package services

import (
	"context"
	"fmt"
	"sync"
	"time"

	"zwai-app/config"
	"zwai-app/db"

	"github.com/volcengine/volc-sdk-golang/service/sms"

	"go.mongodb.org/mongo-driver/bson"
)

// rateLimiter 用于记录每个手机号上次发送时间，保证同一手机号一分钟内只发送一次
var (
	rateLimiter   = make(map[string]time.Time)
	rateLimiterMu sync.Mutex
)

// 场景与模板ID的映射
var sceneMap = map[string]struct {
	TemplateID string
	Scene      string
	Tag        string
}{
	"register": {
		TemplateID: "ST_8565001e",
		Scene:      "register",
		Tag:        "register",
	},
	"login": {
		TemplateID: "ST_84beec9e",
		Scene:      "login",
		Tag:        "login",
	},
	"forgot": {
		TemplateID: "ST_84be9287",
		Scene:      "forgot",
		Tag:        "forgot",
	},
}

// SendVolcengineSMSCode 发送不同场景的验证码，同一手机号一分钟内只发一次
// 返回平台错误码和 error，若发送成功则 code 为空，err 也为 nil
func SendVolcengineSMSCode(phone string, from string) (code string, err error) {

	// 2) 如果是注册场景，先查库看账号（手机号）是否已存在
	if from == "register" {
		coll := db.Client.Database(db.DBName).Collection("User")
		count, err := coll.CountDocuments(context.Background(), bson.M{"account": phone})
		if err != nil {
			return "", fmt.Errorf("校验账号状态失败: %w", err)
		}
		if count > 0 {
			// 不给已注册账号重复发验证码
			return "6", fmt.Errorf("该账号已注册")
		}
	}

	// 限频：同一手机号一分钟内只能发送一次
	rateLimiterMu.Lock()
	if last, ok := rateLimiter[phone]; ok {
		if elapsed := time.Since(last); elapsed < time.Minute {
			rateLimiterMu.Unlock()
			return "", fmt.Errorf("一分钟内只能发送一次，请 %d 秒后再试", int((time.Minute - elapsed).Seconds()))
		}
	}
	rateLimiterMu.Unlock()

	// 场景校验
	cfg := config.Load()
	sceneCfg, ok := sceneMap[from]
	if !ok {
		return "", fmt.Errorf("不支持的验证码场景: %s", from)
	}

	// 设置 SDK 鉴权
	sms.DefaultInstance.Client.SetAccessKey(cfg.AccessKeyID)
	sms.DefaultInstance.Client.SetSecretKey(cfg.SecretAccessKey)

	// 构造请求
	req := &sms.SmsVerifyCodeRequest{
		SmsAccount:  cfg.SmsAccount,
		Sign:        cfg.SignName,
		TemplateID:  sceneCfg.TemplateID,
		CodeType:    6,
		PhoneNumber: phone,
		Tag:         sceneCfg.Tag,
		Scene:       sceneCfg.Scene,
		ExpireTime:  1800,
		TryCount:    5,
	}

	// 调用发送接口
	result, statusCode, err := sms.DefaultInstance.SendVerifyCode(req)

	// 打印调试信息
	// b, _ := json.MarshalIndent(result, "", "  ")
	// fmt.Printf("[SMS DEBUG] req: %+v\n", req)
	// fmt.Printf("[SMS DEBUG] result JSON: %s\n", b)
	// fmt.Printf("[SMS DEBUG] statusCode: %d, err: %v\n", statusCode, err)

	// SDK/网络错误
	if err != nil {
		return "", fmt.Errorf("短信接口调用失败: %w", err)
	}
	// 平台业务错误
	if metaErr := result.ResponseMetadata.Error; metaErr != nil {
		return metaErr.Code, fmt.Errorf("短信服务异常: %s", metaErr.Message)
	}
	// HTTP 状态异常
	if statusCode != 200 {
		return "", fmt.Errorf("短信服务响应异常: %d", statusCode)
	}

	// 成功后记录发送时间
	rateLimiterMu.Lock()
	rateLimiter[phone] = time.Now()
	rateLimiterMu.Unlock()

	return "", nil
}

func VerifyVolcengineSMSCode(phone, from, codeIn string) (code string, err error) {
	cfg := config.Load()
	// SDK 鉴权
	sms.DefaultInstance.Client.SetAccessKey(cfg.AccessKeyID)
	sms.DefaultInstance.Client.SetSecretKey(cfg.SecretAccessKey)

	// 构造校验请求
	req := &sms.CheckSmsVerifyCodeRequest{
		SmsAccount:  cfg.SmsAccount,
		PhoneNumber: phone,
		Code:        codeIn,
		Scene:       from,
	}

	// 调用校验接口
	resp, statusCode, err := sms.DefaultInstance.CheckVerifyCode(req)

	// 打印调试信息
	// func() {
	// 	b, _ := json.MarshalIndent(resp, "", "  ")
	// 	fmt.Printf("[SMS DEBUG][Verify] req=%+v\nresp=%s\nstatusCode=%d err=%v\n",
	// 		req, b, statusCode, err)
	// }()

	if err != nil {
		return "", fmt.Errorf("校验接口调用失败: %w", err)
	}
	// 平台业务错误
	if metaErr := resp.ResponseMetadata.Error; metaErr != nil {
		return metaErr.Code, fmt.Errorf("校验失败: %s", metaErr.Message)
	}
	// HTTP 状态异常
	if statusCode != 200 {
		return "", fmt.Errorf("校验服务响应异常: %d", statusCode)
	}

	// 平台返回的 Result
	result := resp.Result
	switch result {
	case "0":
		// 校验成功
		return "", nil
	case "1":
		return result, fmt.Errorf("验证码错误")
	case "2":
		return result, fmt.Errorf("验证码已过期")
	default:
		return result, fmt.Errorf("未知验证码状态: %s", result)
	}
}
